package com.zhangfuyu.alibaba.service;

import com.alibaba.fastjson.JSON;
import com.zhangfuyu.alibaba.entity.Account;
import com.zhangfuyu.alibaba.entity.AccountLog;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


@Service
public class AccountService {


    @Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        return new ThreadPoolExecutor(10, 10, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), new ThreadPoolExecutor.CallerRunsPolicy());
    }


    @Autowired
    StringRedisTemplate redisTemplate;

    private final static String TRANSFER_ACCOUNTS_STRING = "transFer_accounts_string";

    private final static String TRANSFER_ACCOUNTS_LIST = "transFer_accounts_list";

    /**
     * 转入
     *
     * @param account
     */
    public void toChangeIntoAccounts(Account account) throws InterruptedException {
        /**
         * 分布式环境下添加redis 分布式锁
         */
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(TRANSFER_ACCOUNTS_STRING + account.getUserid(), "", 5, TimeUnit.MINUTES);
        if (aBoolean) {
            try {
                BigDecimal sum = account.getBalance().add(account.getValue());
                account.setBalance(sum);
                AccountLog accountLog = new AccountLog();
                BeanUtils.copyProperties(account, accountLog);
                accountLog.setType(1);
                redisTemplate.opsForSet().add(TRANSFER_ACCOUNTS_LIST + accountLog.getUserid(), JSON.toJSONString(accountLog));
            } catch (Exception e) {
                //循环 redis list 里面的log 数据根据转入转出类型做回滚

            }
        } else {
            TimeUnit.MICROSECONDS.sleep(100);
            toChangeIntoAccounts(account);
        }

    }

    /**
     * 转出
     *
     * @param account
     */
    public void transferOutAccounts(Account account) throws InterruptedException {
        /**
         * 分布式环境下添加redis 分布式锁
         */
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(TRANSFER_ACCOUNTS_STRING + account.getUserid(), "", 5, TimeUnit.MINUTES);
        if (aBoolean) {
            try {
                if (account.getBalance().doubleValue() < account.getValue().doubleValue()) {
                    System.out.println("余额不足...");
                    return;
                }
                BigDecimal sum = account.getBalance().subtract(account.getValue());

                account.setBalance(sum);
                AccountLog accountLog = new AccountLog();
                BeanUtils.copyProperties(account, accountLog);
                accountLog.setType(2);
                redisTemplate.opsForSet().add(TRANSFER_ACCOUNTS_LIST + accountLog.getUserid(), JSON.toJSONString(accountLog));
            } catch (Exception e) {
            }
        } else {
            TimeUnit.MICROSECONDS.sleep(100);
            transferOutAccounts(account);
        }
    }

}
